#!/usr/bin/env bash
# This script pre-processes the Fortran source code for g95
# It does not support REAL32, REAL64, REAL128 in ISO_FORTRAN_ENV.

DIR="$(realpath "$1")"
CONSTSF90="consts.F90"
CONSTS="$DIR/common/$CONSTSF90"
MEMORYF90="memory.F90"
MEMORY="$DIR/common/$MEMORYF90"
STRINGF90="string.f90"
STRING="$DIR/common/$STRINGF90"
CMN_FPRINTF90="fprint.f90"
CMN_FPRINT="$DIR/common/$CMN_FPRINTF90"
MEX_FPRINTF90="fprint.F90"
MEX_FPRINT="$DIR/common/$MEX_FPRINTF90"
UOBYQB="$DIR/uobyqa/uobyqb.f90"
NEWUOB="$DIR/newuoa/newuob.f90"
BOBYQB="$DIR/bobyqa/bobyqb.f90"
LINCOB="$DIR/lincoa/lincob.f90"
COBYLB="$DIR/cobyla/cobylb.f90"

if ! basename "$DIR" | grep -q ".test\|test." || ! [[ -d "$DIR" ]] ; then
    printf "\n%s is not a testing directory.\n\nExit.\n\n" "$DIR"
    exit 1
fi

if [[ -f "$CONSTS" ]] ; then
    sed -i "/end module consts_mod/d" "$CONSTS"

    STR="use, intrinsic :: iso_fortran_env, only : INT16, INT32, INT64, SP => REAL32, DP => REAL64"
    sed -i "/$STR/d" "$CONSTS"
    STR="HP => REAL16"
    sed -i "/$STR/d" "$CONSTS"
    STR="QP => REAL128"
    sed -i "/$STR/d" "$CONSTS"
    OLD_STR="! Define the real kind to be used in the Fortran code."
    NEW_STR="$OLD_STR\ninteger, parameter :: SP = kind(0.0), DP = kind(0.0D0)\n#if PRIMA_QP_AVAILABLE\ninteger, parameter :: QP = selected_real_kind(p=30)\n#endif"
    sed -i "s/$OLD_STR/$NEW_STR/" "$CONSTS"
    OLD_STR="integer, parameter :: IK = INT16"
    NEW_STR="integer, parameter :: IK = selected_int_kind(4)"
    sed -i "s/$OLD_STR/$NEW_STR/" "$CONSTS"
    echo "integer, parameter :: INT16 = selected_int_kind(4)" >> "$CONSTS"
    OLD_STR="integer, parameter :: IK = INT32"
    NEW_STR="integer, parameter :: IK = selected_int_kind(7)"
    sed -i "s/$OLD_STR/$NEW_STR/" "$CONSTS"
    echo "integer, parameter :: INT32 = selected_int_kind(7)" >> "$CONSTS"
    OLD_STR="integer, parameter :: IK = INT64"
    NEW_STR="integer, parameter :: IK = selected_int_kind(14)"
    sed -i "s/$OLD_STR/$NEW_STR/" "$CONSTS"
    echo "integer, parameter :: INT64 = selected_int_kind(14)" >> "$CONSTS"

    echo "end module consts_mod" >> "$CONSTS"
fi

if [[ -f "$MEMORY" ]] ; then
    OLD_STR="y = int(storage_size(x) \/ 8, kind(y))"
    NEW_STR="y = int(8, kind(y))"
    sed -i "s/$OLD_STR/$NEW_STR/" "$MEMORY"
fi

if [[ -f "$STRING" ]] ; then
    sed -i "/ndgt_loc = min(ndgt_loc, floor(real(MAX_NUM_STR_LEN - 5) \/ 2.0))/d" "$STRING"
    sed -i "/nexp_loc = min(nexp_loc, floor(real(MAX_NUM_STR_LEN - 5) \/ 2.0))/d" "$STRING"
fi

for FILE in "$CMN_FPRINT" "$MEX_FPRINT" ; do
    if [[ -f "$FILE" ]] ; then
        sed -i "s|funit_loc = -1|funit_loc = 42|g" "$FILE"
        sed -i "s|newunit|unit|g" "$FILE"
    fi
done

# g95 does not support internal subroutines as arguments.
if [[ -f "$COBYLB" ]] ; then
    sed -ni '1,/\s*!\s*Calculation ends\s*!/p;/end subroutine cobylb/,$p' "$COBYLB"
    sed -i "s|calcfc_internal|calcfc|" "$COBYLB"
fi

for FILE in "$NEWUOB" "$UOBYQB" "$BOBYQB" ; do
    if [[ -f "$FILE" ]] ; then
        sed -i "s|terminate=terminate)|0.0_RP, [0.0_RP], terminate)|g" "$FILE"
    fi
done
if [[ -f "$LINCOB" ]]; then
   sed -i "s|terminate=terminate)|[0.0_RP], terminate)|g" "$LINCOB"
fi

exit 0
